package cn.skycity.common.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.skycity.common.service.ISysRoleMenuService;
import cn.skycity.common.service.ISysRoleService;
import cn.skycity.common.service.ISysUserRoleService;
import cn.skycity.common.service.ISysUserService;
import cn.skycity.framework.core.model.Result;
import cn.skycity.framework.core.utils.StreamUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.skycity.common.log.annotation.Log;
import com.skycity.common.log.enums.BusinessType;
import com.skycity.framework.uaa.pojo.dto.SysRoleBo;
import com.skycity.framework.uaa.pojo.dto.SysUserBo;
import com.skycity.framework.uaa.pojo.entity.SysRole;
import com.skycity.framework.uaa.pojo.entity.SysRoleMenu;
import com.skycity.framework.uaa.pojo.entity.SysUserRole;
import com.skycity.framework.uaa.pojo.vo.SysUserVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author YingBo.Dai
 * @Date 2023/11/5
 * @Version 1.0
 */

@RestController
@RequestMapping("/role")
@Slf4j
public class RoleController {

    @Resource
    private ISysRoleService iSysRoleService;
    @Resource
    private ISysRoleMenuService sysRoleMenuService;
    @Resource
    private ISysUserService iSysUserService;
    @Resource
    private ISysUserRoleService iSysUserRoleService;


    @GetMapping("/page")
    public Result<Page<SysRole>> pageList(Page<SysRole> pageVo, SysRole sysRole) {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<SysRole>()
                .like(StrUtil.isNotBlank(sysRole.getRoleName()), SysRole::getRoleName, sysRole.getRoleName()).or().
                like(StrUtil.isNotBlank( sysRole.getRoleName()), SysRole::getRoleKey,  sysRole.getRoleKey())
                .eq(ObjUtil.isNotNull(sysRole.getStatus()),SysRole::getStatus,sysRole.getStatus())
                .orderByDesc(SysRole::getUpdateTime)
                .orderByDesc(SysRole::getCreateTime);
        Page<SysRole> result = iSysRoleService.page(pageVo, queryWrapper);
        return Result.success(result);
    }


    @Log(title = "角色管理", businessType = BusinessType.INSERT)
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> add(@RequestBody SysRoleBo sysRoleBo){
        if (!iSysRoleService.checkRoleNameUnique(sysRoleBo)) {
            return Result.failed("新增角色'" + sysRoleBo.getRoleName() + "'失败，角色名称已存在");
        } else if (!iSysRoleService.checkRoleKeyUnique(sysRoleBo)) {
            return Result.failed("新增角色'" + sysRoleBo.getRoleName() + "'失败，角色权限已存在");
        }
        SysRole sysRole = BeanUtil.toBean(sysRoleBo, SysRole.class);
        boolean result = iSysRoleService.save(sysRole);
        if (result) {
            List<SysRoleMenu> list = StreamUtils.toList(sysRoleBo.getMenuIds(), menuId -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(sysRole.getId());
                sysRoleMenu.setMenuId(menuId);
                return sysRoleMenu;
            });
            sysRoleMenuService.saveBatch(list);
        }
        return Result.judge(result);
    }

    @GetMapping("/{id}")
    public Result<SysRole> details(@PathVariable("id")Long id){
        return Result.success(iSysRoleService.getById(id));
    }
    /**
     * 获取角色下的所有权限
     * @param roleId
     * @return
     */
    @GetMapping("/{id}/menus")
    public Result<List<Long>> listRoleMenu(@PathVariable("id") Long roleId) {
        List<Long> menuIds = sysRoleMenuService.listMenuIds(roleId);
        return Result.success(menuIds);
    }

    @Log(title = "角色管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{id}")
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> delete(@PathVariable("id")String id){
        List<Long> ids = StrUtil.split(id,",").stream().map(Long::valueOf).collect(Collectors.toList());
        boolean result = iSysRoleService.removeByIds(ids);
        sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids));
        iSysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, ids));
        return Result.judge(result);
    }

    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public Result<?> changeStatus(@RequestBody SysRole sysRole){
        iSysRoleService.update(new LambdaUpdateWrapper<SysRole>().set(SysRole::getStatus,sysRole.getStatus())
                .eq(SysRole::getId,sysRole.getId()));
        return Result.success();
    }

    /**
     * 获取所有角色列列
     * @return
     */
    @GetMapping("/getAllRoleList")
    public Result<List<SysRole>> getAllRoleList(){
        return Result.success(iSysRoleService.list(new LambdaQueryWrapper<SysRole>().eq(SysRole::getStatus, "1")));
    }


//    @SaCheckPermission("system:role:edit")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public Result<Void> edit(@Validated @RequestBody SysRoleBo role) {
//        roleService.checkRoleAllowed(role);
//        roleService.checkRoleDataScope(role.getRoleId());
        if (!iSysRoleService.checkRoleNameUnique(role)) {
            return Result.failed("修改角色'" + role.getRoleName() + "'失败，角色名称已存在");
        } else if (!iSysRoleService.checkRoleKeyUnique(role)) {
            return Result.failed("修改角色'" + role.getRoleName() + "'失败，角色权限已存在");
        }

        if (iSysRoleService.updateRole(role) > 0) {
            iSysRoleService.cleanOnlineUserByRole(role.getId());
            return Result.success();
        }
        return Result.failed("修改角色'" + role.getRoleName() + "'失败，请联系管理员");
    }


    /**
     * 查询已分配角色用户列表
     */
    @GetMapping("/authUser/allocatedList")
    public Result<Page<SysUserVo>> allocatedList(SysUserBo user, Page<SysUserBo> pageVo) {
        return Result.success(iSysUserService.selectAllocatedList(user, pageVo));
    }


    /**
     * 查询没有分配角色的用户列表
     */
    @GetMapping("/authUser/unallocatedList")
    public Result<Page<SysUserVo>> unallocatedList(SysUserBo user, Page<SysUserBo> pageVo) {
        return Result.success(iSysUserService.selectUnallocatedList(user, pageVo));
    }

    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/grant")
    public Result<Void> addAuthUser(Long roleId, Long[] userIds) {
        iSysRoleService.addAuthUser(roleId, userIds);
        return Result.success();
    }

    /**
     * 取消用户授权角色
     */
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/revoke")
    public Result<Void> revokeAuthUser(Long roleId, Long[] userIds) {
        iSysRoleService.revokeAuthUser(roleId, userIds);
        return Result.success();
    }

    /**
     * 修改保存数据权限
     */
//    @SaCheckPermission("system:role:edit")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/dataScope")
    public Result<Void> dataScope(@RequestBody SysRoleBo role) {
        iSysRoleService.checkRoleDataScope(role.getId());
        iSysRoleService.authDataScope(role);
        return Result.success();
    }
}
